﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;

namespace Gfw.Repository
{
    /// <summary>
    /// 数据库访问基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Repository<T> where T : class
    {
        private ISession _session;
        internal virtual ISession Session
        {
            get
            {
                if (_session == null)
                    _session = RepositoryFactory.OpenSession();
                return _session;
            }
        }

        #region 基础操作

        public virtual T Load(string id,UnitOfWork unitOfWork=null)
        {
            if (unitOfWork == null)
            {
                var reslut = Session.Load<T>(id);
                return reslut ?? default(T);
            }
            else
            {
                var reslut = unitOfWork.Load<T>(id);
                return reslut ?? default(T);
            }
        }

        /// <summary>
        /// 得到对象
        /// </summary>
        /// <param name="id">Guid</param>
        /// <param name="unitOfWork"></param>
        /// <returns></returns>
        public virtual T Get(string id, UnitOfWork unitOfWork = null)
        {
            if (unitOfWork == null)
            {
                var reslut = Session.Get<T>(id);
                return reslut ?? default(T);
            }
            else
            {
                var reslut = unitOfWork.Get<T>(id);
                return reslut ?? default(T);
            }
        }



        public virtual void Save(T entity, UnitOfWork unitOfWork = null)
        {
            if (unitOfWork == null)
            {
                ITransaction trans = Session.BeginTransaction();
                try
                {
                    Session.Save(entity);
                    //Session.Flush();
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
            else
            {
                unitOfWork.Save(entity);
            }
        }

        public virtual IEnumerable<T> GetAll(UnitOfWork unitOfWork=null)
        {
            if (unitOfWork == null)
            {
                return Session.CreateCriteria<T>()
                   .List<T>();
            }
            else
            {
                return unitOfWork.Session.CreateCriteria<T>()
                      .List<T>();
            }
        }

        public virtual void SaveOrUpdate(T entity, UnitOfWork unitOfWork = null)
        { if (unitOfWork == null)
            {
                ITransaction trans = Session.BeginTransaction();
                try
                {
            Session.SaveOrUpdate(entity);
            //Session.Flush();
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
            else
            {
                unitOfWork.SaveOrUpdate(entity);
            }
        }
        public virtual void Update(T entity, UnitOfWork unitOfWork = null)
        {
            if (unitOfWork == null)
            {
                ITransaction trans = Session.BeginTransaction();
                try
                {
                    Session.Update(entity);
                    //Session.Flush(); 
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
            else
            {
                unitOfWork.Update(entity);
            }
        }
        public virtual void Delete(string id, UnitOfWork unitOfWork = null)
        {
            if (unitOfWork == null)
            {
                ITransaction trans = Session.BeginTransaction();
                try
                {
                    var entity = Get(id);
                    Session.Delete(entity);
                    // Session.Flush(); 
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
            else
            {
                unitOfWork.Delete<T>(id);
            }
        }
        #endregion 基础操作

        #region 查询分页
        /// <summary>
        /// 数据库的分页查询
        /// </summary>
        /// <param name="hql">查询的hql语句，应该是已经格式化好了的</param>
        /// <param name="pageIndex">当前返回结果的页数，从0开始计数</param>
        /// <param name="pageSize">每页的条数</param>
        /// <param name="totalSize">查询返回的总页数</param>
        /// <returns></returns>
        public IList<T> Query(string hql, int pageIndex, int pageSize, out int totalSize)
        {
            int total = (int)Session.CreateQuery(hql).UniqueResult<long>();
            totalSize = (total + pageSize - 1) / pageSize;

            var query = Session.CreateQuery(hql).SetFirstResult(pageIndex * pageSize).SetMaxResults(pageSize);
            return query.List<T>();
        }
        #endregion
    }
}
